home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Kit PC World De Ampliacion De Windows 95
/
Kit PC World de ampliacion de Windows 95.iso
/
clarion
/
cw15
/
examp15.z
/
LIBMAKER.CLW
< prev
next >
Wrap
Text File
|
1995-09-09
|
13KB
|
447 lines
PROGRAM
INCLUDE('KEYCODES.CLW')
MAP
ReadExecutable
DumpPEExports
DumpNEExports
WriteLib
ReadLib
InfoWindow
END
FileName STRING(255) ! File name for input and output files
! LIBfile is used to read and write import library files
LIBfile FILE,DRIVER('DOS','/FILEBUFFERS=20'),PRE(LIB),CREATE,NAME(FileName)
RECORD
RawBytes BYTE,DIM(1024)
header GROUP,OVER(RawBytes)
typ BYTE ! OMF record type = 88H (Coment)
len USHORT ! Size of OMF record to follow
kind USHORT ! Comment kind = 0A000H
bla BYTE ! Always 1 for our purposes
ordflag BYTE ! ditto
END
! For the records we want, the header is follower by the pubname
! and modname in PSTRING format, then the ordinal export number (USHORT)
pstringval PSTRING(128),OVER(RawBytes)
ushortval USHORT,OVER(RawBytes)
END
END
! EXEfile is used for reading NE and PE format executable files
EXEfile FILE,DRIVER('DOS','/FILEBUFFERS=20'),PRE(EXE),NAME(FileName)
RECORD
RawBytes BYTE,DIM(1024)
cstringval CSTRING(128),OVER(RawBytes)
pstringval PSTRING(128),OVER(RawBytes)
ulongval ULONG,OVER(RawBytes)
ushortval USHORT,OVER(RawBytes)
! DOSheader is the old exe (stub) header format
DOSheader GROUP,OVER(RawBytes)
dos_magic STRING(2) ! contains 'MZ'
dos_filler USHORT,DIM(29) ! we don't care about these fields
dos_lfanew ULONG ! File offset of new exe header
END
! NEheader is the new exe (16-bit) header format
NEheader GROUP,OVER(RawBytes)
ne_magic STRING(2) ! Contains 'NE'
ne_ver BYTE
ne_rev BYTE
ne_enttab USHORT
ne_cbenttab USHORT
ne_crc LONG
ne_flags USHORT
ne_autodata USHORT
ne_heap USHORT
ne_stack USHORT
ne_csip ULONG
ne_sssp ULONG
ne_cseg USHORT
ne_cmod USHORT
ne_cbnrestab USHORT
ne_segtab USHORT
ne_rsrctab USHORT
ne_restab USHORT
ne_modtab USHORT
ne_imptab USHORT
ne_nrestab ULONG
ne_cmovent USHORT
ne_align USHORT
ne_rescount USHORT
ne_osys BYTE
ne_flagsother BYTE
ne_gangstart USHORT
ne_ganglength USHORT
ne_swaparea USHORT
ne_expver USHORT ! Expected Window version number
END
! PEheader is the flat-model (32-bit) header format (PE signature)
PEheader GROUP,OVER(RawBytes)
pe_signature ULONG
pe_machine USHORT
pe_nsect USHORT
pe_stamp ULONG
pe_psymbol ULONG
pe_nsymbol ULONG
pe_optsize USHORT
pe_character USHORT
END
! SectHeader describes a section in a PE file
SectHeader GROUP,OVER(RawBytes)
sh_SectName CSTRING(8)
sh_VirtSize ULONG
sh_PhysAddr ULONG,OVER(sh_VirtSize)
sh_VirtAddr ULONG
sh_RawSize ULONG
sh_RawPtr ULONG
sh_Reloc ULONG
sh_LineNum ULONG
sh_RelCount USHORT
sh_LineCount USHORT
sh_Character ULONG
END
! ExpDirectory is at start of a .edata section in a PE file
ExpDirectory GROUP,OVER(RawBytes)
exp_Character ULONG
exp_stamp ULONG
exp_Major USHORT
exp_Minor USHORT
exp_Name ULONG
exp_Base ULONG
exp_NumFuncs ULONG
exp_NumNames ULONG
exp_AddrFuncs ULONG
exp_AddrNames ULONG
exp_AddrOrds ULONG
END
END
END
newoffset ULONG ! File offset to NE/PE header
ExportQ QUEUE,PRE(EXQ)
symbol STRING(128)
icon SHORT
treelevel SHORT
ordinal USHORT
module STRING(20)
END
oldheight USHORT
oldwidth USHORT
xdelta SHORT
ydelta SHORT
float REAL
window WINDOW('LibMaker'),AT(,,178,123),CENTER,IMM,ICON('LIBRARY.ICO'),ALRT(DeleteKey),SYSTEM,GRAY,RESIZE
LIST,AT(13,10,150,65),FONT('Arial',8,,FONT:regular),USE(?List1),DISABLE,VSCROLL,COLUMN,FORMAT('130L(5)IT(L)20L@N_5B@'), |
FROM(ExportQ)
BUTTON('&Add file...'),AT(13,83,40,14),USE(?AddFile)
BUTTON('&Save as...'),AT(69,83,40,14),USE(?SaveAs),DISABLE
BUTTON('Info...'),AT(127,83,40,14),USE(?Info)
BUTTON('Clear'),AT(36,105,40,14),USE(?Clear)
BUTTON('&Close'),AT(103,105,40,14),USE(?Close),STD(STD:Close)
END
CODE
OPEN(window)
?List1{PROP:iconlist, 1} = '~Opened.ico'
?List1{PROP:iconlist, 2} = '~Closed.ico'
oldheight = window{PROP:height}
oldwidth = window{PROP:width}
window {PROP:minheight} = oldheight
window {PROP:minwidth} = oldwidth
ACCEPT
CASE ACCEPTED()
OF ?Info
InfoWindow
OF ?Clear
FREE(ExportQ)
DISABLE(?SaveAs)
DISPLAY
OF ?AddFile
IF FileDialog('Import symbols from file ...', FileName, |
'DLL files (*.dll)|*.dll|LIB files (*.lib)|*.lib|All files (*.*)|*.*', |
FALSE)
DISPLAY
SetCursor(CURSOR:Wait)
IF INSTRING('.LIB', UPPER(FileName), 1, 1)
ReadLib
ELSE
ReadExecutable
END
SetCursor()
END
DO EnableControls
OF ?SaveAs
IF RECORDS(ExportQ)>0
CLEAR(FileName)
IF FileDialog('Output library definition to ...', FileName, 'Library files (*.lib)|*.lib|Export files (*.exp)|*.exp', TRUE)
WriteLib
END
END
END
CASE EVENT()
OF EVENT:expanded
OROF EVENT:contracted
i# = ?List1{PROPLIST:MouseDownRow}
GET(ExportQ, i#)
exq:treelevel = -exq:treelevel
IF exq:icon = 1
exq:icon = 2
ELSE
exq:icon = 1
END
PUT(ExportQ)
DISPLAY(?list1)
OF EVENT:Sized
ydelta = window{PROP:height}-oldheight
xdelta = window{PROP:width}-oldwidth
SetPosition(?AddFile,,?AddFile{PROP:ypos}+ydelta)
SetPosition(?SaveAs,?SaveAs{PROP:xpos}+xdelta/2,?SaveAs{PROP:ypos}+ydelta)
SetPosition(?Close,?Close{PROP:xpos}+xdelta,?Close{PROP:ypos}+ydelta)
SetPosition(?List1,,,?List1{PROP:width}+xdelta, ?list1{PROP:height}+ydelta)
oldheight = window{PROP:height}
oldwidth = window{PROP:width}
OF EVENT:AlertKey
IF KeyCode()=DeleteKey
GET(ExportQ, CHOICE(?List1))
DELETE(ExportQ)
IF (exq:treelevel<2)
GET(ExportQ, CHOICE(?List1))
LOOP WHILE (exq:treelevel=2)
DELETE(ExportQ)
GET(ExportQ, CHOICE(?List1))
IF (ERRORCODE())
BREAK
END
END
END
DO EnableControls
DISPLAY(?list1)
END
END
END
EnableControls ROUTINE
IF RECORDS(ExportQ)
ENABLE(?list1)
ENABLE(?SaveAs)
ELSE
DISABLE(?list1)
ENABLE(?SaveAs)
END
! ReadExecutable gets export table from 16 or 32-bit file or LIB file
ReadExecutable PROCEDURE
sectheaders ULONG ! File offset to section headers
sections USHORT ! File offset to section headers
CODE
OPEN(EXEfile, 0)
GET(EXEfile, 1, SIZE(EXE:DOSheader))
IF EXE:dos_magic = 'MZ' THEN
newoffset = EXE:dos_lfanew
GET(EXEfile, newoffset+1, SIZE(EXE:PEheader))
IF EXE:pe_signature = 04550H THEN
sectheaders = EXE:pe_optsize+newoffset+SIZE(EXE:PEheader)
sections = EXE:pe_nsect
LOOP i# = 1 TO sections
GET(EXEfile,sectheaders+1,SIZE(EXE:sectheader))
sectheaders += SIZE(EXE:sectheader)
IF EXE:sh_SectName = '.edata' THEN
DumpPEExports
END
END
ELSE
GET(EXEfile, newoffset+1, SIZE(EXE:NEheader))
DumpNEExports
END
END
CLOSE(EXEfile)
! DumpPEexports gets export table from a PE format file (32-bit)
DumpPEExports PROCEDURE
RawPtr ULONG
VirtAddr ULONG
NumNames ULONG
Names ULONG
Ordinals ULONG
Base ULONG
j USHORT
CODE
RawPtr = EXE:sh_rawptr
VirtAddr = EXE:sh_virtaddr
GET(EXEfile, RawPtr+1, SIZE(EXE:ExpDirectory))
NumNames = EXE:exp_NumNames
Names = EXE:exp_AddrNames
Ordinals = EXE:exp_AddrOrds
Base = EXE:exp_Base
GET(EXEfile, RawPtr-VirtAddr+EXE:exp_Name+1, SIZE(EXE:cstringval))
exq:Module = EXE:cstringval
exq:Symbol = EXE:cstringval
exq:treelevel = 1
exq:icon = 1
exq:ordinal = 0
ADD(ExportQ)
exq:treelevel = 2
exq:icon = 0
LOOP j = 0 TO NumNames-1
GET(EXEfile, RawPtr-VirtAddr+Names+j*4+1, SIZE(EXE:ulongval))
GET(EXEfile, RawPtr-VirtAddr+EXE:ulongval+1, SIZE(EXE:cstringval))
exq:symbol = EXE:cstringval
GET(EXEfile, RawPtr-VirtAddr+Ordinals+j*2+1, SIZE(EXE:ushortval))
exq:ordinal = EXE:ushortval+Base
ADD(ExportQ)
END
! DumpNEexports gets export table from a NE format file (16-bit)
DumpNEExports PROCEDURE
j ULONG
CODE
! First get the module name - stored as first entry in non-resident name table
j = EXE:ne_nrestab+1
GET(EXEfile, newoffset+EXE:ne_restab+1, SIZE(EXE:pstringval))
exq:Module = EXE:pstringval
exq:symbol = EXE:pstringval
exq:ordinal = 0
exq:treelevel = 1
exq:icon = 1
ADD(ExportQ)
! Now pull apart the resident name table. First entry is the description, and is skipped
exq:treelevel = 2
exq:icon = 0
GET(EXEfile, j, SIZE(EXE:pstringval))
j += LEN(EXE:pstringval)+1
GET(EXEfile, j, SIZE(EXE:ushortval))
j += 2
LOOP
GET(EXEfile, j, SIZE(EXE:pstringval))
IF LEN(EXE:pstringval)=0 THEN
BREAK
END
exq:symbol = EXE:pstringval
j += LEN(EXE:pstringval)+1
GET(EXEfile, j, SIZE(EXE:ushortval))
j += 2
exq:ordinal = EXE:ushortval
ADD(ExportQ)
END
! WriteLib writes out all info in the export Q to a LIB file
WriteLib PROCEDURE
i USHORT
CODE
CREATE(LIBfile)
OPEN(LIBfile)
LOOP i = 1 TO RECORDS(ExportQ)
GET(ExportQ, i)
IF exq:treelevel=2 THEN
! Record size is length of the strings, plus two length bytes, a two byte
! ordinal, plus the header length (excluding the first three bytes)
LIB:typ = 88H
LIB:kind = 0A000H
LIB:bla = 1
LIB:ordflag = 1
LIB:len = LEN(CLIP(exq:module))+LEN(CLIP(exq:symbol))+2+2+SIZE(LIB:header)-3
ADD(LIBfile, SIZE(LIB:header))
LIB:pstringval = CLIP(exq:symbol)
ADD(LIBfile, LEN(LIB:pstringval)+1)
LIB:pstringval = CLIP(exq:module)
ADD(LIBfile, LEN(LIB:pstringval)+1)
LIB:ushortval = exq:ordinal
ADD(LIBfile, SIZE(LIB:ushortval))
END
END
CLOSE(LIBfile)
! Readlib reads back in a LIB file output by WriteLib above or by IMPLIB etc
ReadLib PROCEDURE
i USHORT
j USHORT
lastmodule STRING(20)
modulename STRING(20)
symbolname STRING(128)
ordinal USHORT
CODE
OPEN(LIBfile, 0)
i = 1
LOOP
GET(LIBfile, i, SIZE(LIB:header)) ! Read next OMF record
IF ERRORCODE() OR LIB:typ = 0 OR LIB:len = 0 THEN
BREAK ! All done
END
j = i + SIZE(LIB:header) ! Read export info from here
i = i + LIB:len + 3 ! Read next OMF record from here
IF LIB:typ = 88H AND LIB:kind = 0A000H AND LIB:bla = 1 AND LIB:ordflag = 1 THEN
GET(LIBfile, j, SIZE(LIB:pstringval))
symbolname = LIB:pstringval
j += LEN(LIB:Pstringval)+1
GET(LIBfile, j, SIZE(LIB:pstringval))
modulename = LIB:pstringval
j += LEN(LIB:Pstringval)+1
GET(LIBfile, j, SIZE(LIB:ushortval))
ordinal = LIB:ushortval
IF modulename <> lastmodule ! A LIB can describe multiple DLLs
lastmodule = modulename
exq:treelevel = 1
exq:icon = 1
exq:symbol = modulename
exq:module = modulename
exq:ordinal = 0
ADD(ExportQ)
END
exq:treelevel = 2
exq:icon = 0
exq:symbol = symbolname
exq:module = modulename
exq:ordinal = ordinal
ADD(ExportQ)
END
END
CLOSE(LIBfile)
InfoWindow PROCEDURE
infowin WINDOW('LibMaker Info'),AT(,,217,102),GRAY
STRING('This program is provided as both a valuable utility'),AT(16,6),USE(?String1)
STRING('and'),AT(16,20),FONT(,,,FONT:italic),USE(?String2)
STRING('as a source code example. The original executable'),AT(34,20),USE(?String3)
STRING('program is installed in the BIN subdirectory. If you wish'),AT(16,34),USE(?String4)
STRING('to make modifications to the example source, make sure'),AT(16,48),USE(?String5)
STRING('that you are aware of this additional executable.'),AT(16,62),USE(?String6)
BUTTON('OK'),AT(91,81,35,14),USE(?OkButton),STD(STD:Close),DEFAULT
END
CODE
OPEN(infowin)
ACCEPT
CASE EVENT()
OF EVENT:Accepted
CASE FIELD()
OF ?OKButton
BREAK
END
END
END